using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Sirenix.OdinInspector;
using UnityEditor;
using UnityEngine;

/// <summary>
/// 用于创建 art_res/map/**/prefbs 路径下的变体对象
/// </summary>
[InlineEditor]
public class AssetVariantManager : SerializedScriptableObject
{
    private const string defaultPath = "Assets/AssetVariantManagement.asset";
    private static AssetVariantManager _manager;

    public static AssetVariantManager Instance
    {
        get
        {
            Init();
            return _manager;
        }
    }

    [InfoBox("功能介绍：\n1.ExtraPath 选择 art_res 相关路径填入（不支持其他路径） \n2.含有对象丢失列表显示两种情况，丢失原文件或者丢失变体。\n处理方案：\n丢失源文件，删除变体，重新导出检查。\n丢失变体，可能是由于guid 改变，请检查svn")]
    [FolderPath] public List<string> ExtraFolderPath = new List<string>();

    /// <summary>
    /// <original_guid, variant_guid>
    /// </summary>
    [SerializeField] public Dictionary<string, string> ArtPrefabsGuid;

    // // 用于测试的
    // [LabelText("本次变化的 Guid")] public List<string> haveChangedGuidList;

    [LabelText("全丢失对象")] public Dictionary<string, GameObject> rmGuids;

    [LabelText("含有丢失对象")] public Dictionary<string, GameObject> lostGuids = new Dictionary<string, GameObject>();

    public static AssetVariantManager Init()
    {
        _manager = AssetDatabase.LoadAssetAtPath<AssetVariantManager>(defaultPath);
        if (_manager == null)
        {
            _manager = CreateInstance<AssetVariantManager>();

            AssetDatabase.CreateAsset(_manager, defaultPath);

            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh();
        }

        if (_manager.ArtPrefabsGuid == null)
            _manager.ArtPrefabsGuid = new Dictionary<string, string>();

        // if (_manager.haveChangedGuidList == null)
        //     _manager.haveChangedGuidList = new List<string>();

        if (_manager.rmGuids == null)
            _manager.rmGuids = new Dictionary<string, GameObject>();

        if (_manager.lostGuids == null)
            _manager.lostGuids = new Dictionary<string, GameObject>();

        return _manager;
    }

    [Button("拷贝 art_res 到 art_res_Variant", ButtonSizes.Large), GUIColor(0.3f, .8f, .3f)]
    public void CopyVariant()
    {
        if (_manager == null)
            _manager = AssetVariantManager.Init();

        // base 
        // _manager.CopyPrefabs("Assets/art_res/map");

        // other
        if (ExtraFolderPath != null && ExtraFolderPath.Count > 0)
        {
            for (int i = 0; i < ExtraFolderPath.Count; i++)
            {
                var path = ExtraFolderPath[i];
                if (!string.IsNullOrEmpty(path))
                {
                    _manager.CopyPrefabs(path);
                }
            }

            CheckGuid();
        }
    }

    ///
    /// 拷贝 prefabs 下的文件到变体文件夹
    /// 
    public void CopyPrefabs(string folder)
    {
        if (rmGuids.Count > 0 || lostGuids.Count > 0)
        {
            EditorUtility.DisplayDialog("对象丢失", "请先清理异常队列", "确认", "取消");
            Debug.LogError("[AssetVariantManager] 请先清理异常队列");
            return;
        }

        try
        {
            var files = Directory.GetFiles(folder, "*", SearchOption.AllDirectories).Where(f => f.EndsWith(".prefab"))
                .ToArray();
            var parentFolderName = Path.GetFileName(Directory.GetParent(folder).FullName);
            for (int j = 0; j < files.Length; j++)
            {
                var file = files[j];
                // Assets/...relaPath
                var prefabPath = AAManagementUtils.GetAssetPath(file);
                // fileName
                var fileName = Path.GetFileName(file);
                // generate folder
                var destfolder = prefabPath.Replace(fileName, "").Replace("\\", "/").Replace("art_res", "art_res_Variant");
                var destPath = "Assets/art_res_Variant";
                // create folder
                if (!AssetDatabase.IsValidFolder(destfolder))
                {
                    bool start = false;
                    var pfs = destfolder.Split('/');
                    for (int i = 0; i < pfs.Length; i++)
                    {
                        if (string.IsNullOrEmpty(pfs[i]))
                            break;

                        string path = destPath;
                        if (start) path += "/" + pfs[i];

                        if (!AssetDatabase.IsValidFolder(path))
                            AssetDatabase.CreateFolder(destPath, pfs[i]);

                        destPath = path;
                        if (pfs[i].Equals("art_res_Variant"))
                            start = true;
                    }
                }
                else
                    destPath = destfolder;

                // 获取 art_res prefab 对象
                var varPath = AAManagementUtils.GetAssetPath($"{destPath}/{fileName}");
                // 检查对象变体是否已存在
                var tObj = AssetDatabase.LoadAssetAtPath<GameObject>(varPath);
                if (tObj != null)
                {
                    continue;
                }
                
                // 原对象是否存在
                var obj = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);
                if (obj == null)
                {
                    Debug.LogError("[AssetVariantManager] 原资源丢失：" + fileName);
                    continue;
                }

                obj = PrefabUtility.InstantiatePrefab(obj) as GameObject;
                var origin_guid = AssetDatabase.AssetPathToGUID(prefabPath);

                // 创建新的变体对象
                PrefabUtility.SaveAsPrefabAssetAndConnect(obj, varPath, InteractionMode.AutomatedAction);
                var nguid = AssetDatabase.AssetPathToGUID(varPath);

                if (ArtPrefabsGuid.ContainsKey(origin_guid))
                {
                    // if (ArtPrefabsGuid[origin_guid] != nguid)
                    //     haveChangedGuidList.Add(nguid);
                }
                else
                {
                    ArtPrefabsGuid.Add(origin_guid, nguid);
                }

                DestroyImmediate(obj);
            }
        }
        catch (Exception e)
        {
            Debug.LogError("[AssetVariantManager] copy variant error: " + e);
        }
    }

    // 排查原 prefabs 是否有丢失，弹框是否要丢弃无效对象
    public void CheckGuid()
    {
        if (ArtPrefabsGuid == null || ArtPrefabsGuid.Count <= 0)
            return;

        foreach (var pair in ArtPrefabsGuid)
        {
            var aObj = AssetDatabase.LoadAssetAtPath<GameObject>(AssetDatabase.GUIDToAssetPath(pair.Key) ?? "");
            var vObj = AssetDatabase.LoadAssetAtPath<GameObject>(AssetDatabase.GUIDToAssetPath(pair.Value) ?? "");
            // all lost
            if (aObj == null && vObj == null)
            {
                Debug.LogError("[AssetVariantManager] Remove 全资源丢失 guid: " + pair.Key);
                rmGuids.Add(pair.Key, null);
            }
            // lost original obj 
            else if (aObj == null && vObj != null)
            {
                Debug.LogError("[AssetVariantManager] Remove 原资源丢失 guid: " + pair.Key);
                lostGuids.Add(pair.Key, vObj);
            }
            // lost tempObj = generator failed
            else if (aObj != null && vObj == null)
            {
                Debug.LogError("[AssetVariantManager] 变体资源丢失 guid: " + pair.Value);
                lostGuids.Add(pair.Key, aObj);
            }
            else
            {
                // Debug.Log();
            }
        }

        if (lostGuids?.Count > 0 && EditorUtility.DisplayDialog("对象丢失", "含有美术资源变体丢失，请排查", "确认", "取消"))
        {
            // foreach (var pair in lostGuids)
            // {
            //     Debug.LogError("[AssetVariantManager] prefab variant lost: " + pair.Key);
            // }
        }
    }

    [Button("清理全丢失对象")]
    public void ClearRmTargets()
    {
        if(rmGuids == null)
        {
            rmGuids = new Dictionary<string, GameObject>();
            Debug.Log("[AssetVariantManager] 清理完成 rm");
            
            return;
        }

        foreach (var pairs in rmGuids)
        {
            ArtPrefabsGuid.Remove(pairs.Key);
        }
        
        rmGuids.Clear();
        Debug.Log("[AssetVariantManager] 清理完成 rm");
    }


    [Button("清理已排查丢失对象")]
    public void ClearLostList()
    {
        if(lostGuids == null)
        {
            lostGuids = new Dictionary<string, GameObject>();
            Debug.Log("[AssetVariantManager] 清理完成 lost");
            
            return;
        }
        
        foreach (var pairs in lostGuids)
        {
            if (ArtPrefabsGuid.ContainsKey(pairs.Key))
            {
                ArtPrefabsGuid.Remove(pairs.Key);
            }
            else
            {
                Debug.LogError("[AssetVariantManager] 清理失败: " + pairs.Key);
            }
        }
        
        lostGuids.Clear();
        Debug.Log("[AssetVariantManager] 清理完成 rm");
    }
}

/// <summary>
/// Asset 管理工具类
/// </summary>
public class AssetDatabaseUtil
{
    /// <summary>
    /// 移动资源
    /// </summary>
    /// <param name="files"></param>
    /// <param name="destPath"></param>
    private static void MoveAsset(string[] files, string destPath)
    {
        for (int i = 0; i < files.Length; i++)
        {
            // move to 
            var file = files[i];
            var fileName = Path.GetFileName(file);
            var foldPath = AAManagementUtils.CreateParentDirectory(file, destPath);
            var relaPath = AAManagementUtils.GetAssetPath(file);
            var relaDestFold = AAManagementUtils.GetAssetPath(foldPath);

            // UnityTool
            AssetDatabase.MoveAsset(relaPath, $"{relaDestFold}/{fileName}");
        }

        AssetDatabase.Refresh();
    }
}